﻿using ZeroBug.EasyFlow.Core;
using ZeroBug.EasyFlow.Motion;
using ZeroBug.EasyFlow.Machine;
using Microsoft.Extensions.DependencyInjection;

namespace ZeroBug.EasyFlow.Steps
{
    public class AxisMoveStep : IStep
    {
        public bool IgnoreChildren { get; set; }
        public string Icon { get; set; } = "Gauge";
        public bool IsSingleRun { get; set; }
        public int ChildrenIndex { get; set; }
        public Core.Step? NextStep { get; set; }
        public bool Compile(FlowBase flow, ZeroBug.EasyFlow.Core.Step step, out string errInfo)
        {
            errInfo = string.Empty;
            return step.CheckParameters(out errInfo, "AxisNames", "Position", "Offset", "AsyncRun");
        }

        public object GetForm()
        {
            return new AxisMoveStepForm();
        }

        public StepInfo GetInfo()
        {
            StepInfo info = new StepInfo();
            info.StepName = "AxisMove";
            info.Group = StepGroup.Motion;
            info.ImagePath = "pack://application:,,,/ZeroBug.EasyFlow.Step;component/Images/条件.png";
            return info;
        }

        public void OnChildrenEnter()
        {
        }

        public void OnChildrenLeave()
        {

        }

        public bool Prepare(FlowBase flow, ZeroBug.EasyFlow.Core.Step step, out string errInfo)
        {
            errInfo = string.Empty;
            return true;
        }

        public void RegisterVariables(FlowBase flow, ZeroBug.EasyFlow.Core.Step step)
        {
            if (flow.GetFlowManager().VariableManager.GetVariable($"{step.Description}.Completed") == null)
            {
                Variable taskCompleted = new Variable($"{step.Description}.Completed", string.Empty, VariableType.Boolean);
                taskCompleted.GetCurrentValues = () =>
                {
                    return new string[] { task.IsCompleted.ToString() };
                };
                flow.GetFlowManager().VariableManager.AddVariable(taskCompleted, VariableFrom.Local);
            }
        }
        Task? task;
        public StepResult Run(FlowBase flow, ZeroBug.EasyFlow.Core.Step step, out string errInfo)
        {
            errInfo = "";

            if (step.Parameters["AsyncRun"] != null && Convert.ToBoolean(step.Parameters["AsyncRun"].GetEquivalent()[0]))
            {
                while(task?.IsCompleted == false)
                {
                    Thread.Sleep(20);
                }
                task = Task.Run(() =>
                {
                    method(step);
                });
            }
            else
                method(step);

            return StepResult.Success;
        }
        private void method(ZeroBug.EasyFlow.Core.Step step)
        {
            Variable axis = step.Parameters["AxisNames"].GetEquivalent();
            Variable pos = step.Parameters["Position"].GetEquivalent();
            Variable os = step.Parameters["Offset"].GetEquivalent();
            for (int i = 0; i < axis.Count; i++)
            {
                Axis? a = LocalMachine.Services.GetService<MachineResource<Axis, IAxis>>()?.Value?[axis[i]];
                a.MoveAbsolute(Convert.ToDouble(pos[i] + Convert.ToDouble(os[i])), out string stopReason, MotionWorkMode.Auto, null, false);
            }
            if (false)
            {
                for (int i = 0; i < axis.Count; i++)
                {
                    Axis? a = LocalMachine.Services.GetService<MachineResource<Axis, IAxis>>()?.Value?[axis[i]];
                    a.WaitAxisInPosition(Convert.ToDouble(pos[i] + Convert.ToDouble(os[i])), MotionWorkMode.Auto, out string stopReason);
                }
            }

            Random random = new Random();
            Thread.Sleep(random.Next(100, 400));
        }

        public string GetTip(Core.Step step)
        {
            return "";
        }

        public (SerializableDictionary<string, VariableExpression>, List<VariableJudge>) GetParametersAndConditions()
        {
            SerializableDictionary<string, VariableExpression> paras = new SerializableDictionary<string, VariableExpression>();
            paras.Add("AxisNames", new VariableExpression("AxisNames"));
            paras.Add("Position", new VariableExpression("Position", VariableType.Numeric));
            paras.Add("Offset", new VariableExpression("Offset", VariableType.Numeric));
            paras.Add("AsyncRun", new VariableExpression("AsyncRun", VariableType.Boolean));

            return (paras, new List<VariableJudge>());
        }

        public void UnRegisterVariables(FlowBase flow, Core.Step step)
        {
        }
    }
}
